<?php

/**
 *    unit test case for the db testing
 *    mainly used for the etl task 
 */
abstract class Test_Case_DB extends Test_Case{

    /**
     *    The dblink for the test
     *    All the test method use
     *    this link created by __construct
     */
    private $dblink = null;
    
    /**
     *    The DB connect string
     */
    public  $constr = false;

    /**
     *    Create the DB Test Case with dblink created!
     *    @access public
     */
    function __construct(){
        if (! $this->constr) {
            die("can not run without the connect string\n");
        }
        $this->dblink = pg_connect($this->constr) or die("can not connect to the database\n");
        pg_query($this->dblink,"SET NAMES 'utf8';");
        parent::__construct();
    }

    /**
     *    Unset the dblink when the case close
     */
    function __destruct(){
        if(isset($this->dblink) && $this->dblink != null){
            pg_close($this->dblink);
            unset($this->dblink);
        }
    }

    /**
     *    Execute the sql through the dblink
     *    @param string $sql    the sql query string
     *    @access private
     */
    private function executeSql($sql){
        return pg_query($sql);
    }

    /**
     *    When the sql result should be compare with 
     *    a scalar value, you can use this assert.
     *    @param string $sqlstr        the sql query string
     *    @param mixed  $expect        the expect value 
     *    @access public 
     */
    function assertScalarEqual($sqlstr,$expect){
        $resultArray = pg_fetch_array($this->executeSql($sqlstr));
        return $this->assert(
                new Expectation_Equal($resultArray[0]),
                $expect);
    }

    /**
     *    When you  need some customize logic 
     *    to check the result, you can use this.
     *    @param  string $sql           the sql query string
     *    @param  function $customize   the user defined callback function
     *    @access public
     */
    function assertCustomize($sql,$customize){
        $resource = $this->executeSql($sql);
        $result = array();
        while($result[] = pg_fetch_array($resource)); 
        array_pop($result);
        pg_free_result($resource);
        if(call_user_func_array($customize,array($result)))
            return $this->pass();
        else
            return $this->fail();
    }

    /**
     *    When the sql result is a dataset
     *    and the compared value is a dataset
     *    you can use this assert!
     *    @param string $sql_act        the act sql query
     *    @param string $sql_exp        the exp sql query
     *    @access public
     */
    function assertSqlResult($sql_act,$sql_exp){
        $resource_act = $this->executeSql($sql_act);
        $resource_exp = $this->executeSql($sql_exp);
        $act_rows = pg_num_rows($resource_act);
        $exp_rows = pg_num_rows($resource_exp);
        if($act_rows !== $exp_rows){
            pg_free_result($resource_act);
            pg_free_result($resource_exp);
            return $this->fail("rows count does not match for[$act_rows, $exp_rows]");
        }else{
            $actArray = pg_fetch_all($resource_act);
            $expArray = pg_fetch_all($resource_exp);
            pg_free_result($resource_act);
            pg_free_result($resource_exp);
            $res = $this->assert(new Expectation_DB($actArray),$expArray,"%s");
            return $res;
        }
    }
}

?>
